package frame;

import java.awt.Cursor;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.border.Border;
import javax.swing.plaf.metal.DefaultMetalTheme;
import javax.swing.plaf.metal.MetalLookAndFeel;

import org.apache.log4j.Logger;

import util.CsvFilter;
import util.ProgressBar;
import util.ResultTable;
import util.SystemUtil;

/**
 * @author Rishi Das Roy
 *
 * @Organization Institute Of Genomics & Integrative Biology
 */
public class StartGUI extends JFrame implements ActionListener {
	public static final String MULTIPLE_FASTA = "Multiple Protein Sequences in FASTA format";

	private static Logger log = Logger.getLogger(StartGUI.class);

	private static StartGUI mStartGUI;

	private ResultTable mResultTable;

	private JPanel mainPanel;

	private JTextArea mTextSeq;

	private JButton mOpenButton;

	private JButton mPredictButton;

	private JButton mHelpButton;

	private String mFastaFilePath;

	private JTextArea mlog;

	private JTabbedPane mSeriesTabPane;

	private JTextField mFileField;

	private JButton mSave;

	private JButton mResetButton;;

	private StartGUI() {
		validateEnvironment(this);
		mainWindow();
	}

	private void mainWindow() {
		setTitle("GDP:GroEL Dependency Predictor");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//		setSize(810, 330);
		//setResizable(false);
		mainPanel = new JPanel(new GridBagLayout());
		add(mainPanel);

		mTextSeq = new JTextArea(6, 65);
		mTextSeq.setText(MULTIPLE_FASTA);
		mTextSeq.addFocusListener(new FastaFocusListener());
		//mTextSeq.setMargin(new Insets(5,5,5,5));

		JScrollPane mTextSeqPane = new JScrollPane(mTextSeq);

		JPanel lInputPanel = new JPanel(new GridBagLayout());
		Border lInputBorder = BorderFactory
				.createTitledBorder("Input Protein Sequences");
		lInputPanel.setBorder(lInputBorder);
		addGridBagItem(lInputPanel, mTextSeqPane, 0, 0, 4, 1,
				GridBagConstraints.CENTER, GridBagConstraints.BOTH);

		mFileField = new JTextField(51);
		mFileField.setEditable(false);
		addGridBagItem(lInputPanel, mFileField, 0, 1, 2, 1,
				GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);
		mOpenButton = new JButton("FASTA file");
		mOpenButton.addActionListener(this);
		addWindowListener(new WindowAdapter() {
			public void windowOpened(WindowEvent e) {
				mOpenButton.requestFocus();
			}
		});

		mOpenButton.requestFocus(true);
		addGridBagItem(lInputPanel, mOpenButton, 2, 1, 1, 1,
				GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);

		mResetButton = new JButton("Reset");
		mResetButton.addActionListener(this);
		addGridBagItem(lInputPanel, mResetButton, 3, 1, 1, 1,
				GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);

		addGridBagItem(mainPanel, lInputPanel, 0, 0, 3, 1,
				GridBagConstraints.CENTER, GridBagConstraints.BOTH);

		mPredictButton = new JButton("Predict GroEL Dependency");
		mPredictButton.addActionListener(this);
		addGridBagButton(mainPanel, mPredictButton, 0, 1, 1, 1,
				GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);

		mSave = new JButton("Save Result");
		mSave.setEnabled(false);
		mSave.addActionListener(this);
		//mOpenButton.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		addGridBagButton(mainPanel, mSave, 1, 1, 1, 1,
				GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);

		mHelpButton = new JButton("ReadMe");
		mHelpButton.addActionListener(this);
		//mHelpButton.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		addGridBagButton(mainPanel, mHelpButton, 2, 1, 1, 1,
				GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);

		mlog = new JTextArea(5, 50);
		//        mlog.setMargin(new Insets(5,5,5,5));
		//        addGridBagItem(mainPanel, mlog, 0, 4, 2, 1,
		//				GridBagConstraints.CENTER,GridBagConstraints.BOTH);

		JPanel lOutPanel = new JPanel(new GridBagLayout());
		mSeriesTabPane = new JTabbedPane();
		mSeriesTabPane.setPreferredSize(new Dimension(750,175));
		mSeriesTabPane.setVisible(false);
		//        mSeriesTabPane.setPreferredSize(new Dimension(800,150));
		//        mSeriesTabPane.setBorder(BorderFactory.createLineBorder(Color.BLACK));
		addGridBagItem(lOutPanel, mSeriesTabPane, 0, 0, 1, 1,
				GridBagConstraints.CENTER, GridBagConstraints.BOTH);

		java.net.URL imgURL = this.getClass().getResource(
				"/Application/IGIB.jpeg");
		String lIGIB = imgURL.getPath();

		String lAbout = "<html><body>"
				+
				//		"<center>"+
				"Developed By: <font size=+1>"
				+ "<a href=\"http://igib.res.in/\">Institute of Genomics "
				+ "and  " + "Integrative Biology</a> </font>"
				+ "<img src=\"jar:" + lIGIB + "\"/><br clear=\"all\">" +
				//"Report bug: <a href=\"mailto:ddash@igib.in\">ddash@igib.in</a>"+
				//		"</center>"+
				"</body></html>";
		JLabel lInPutLabel1 = new JLabel(lAbout);
		lInPutLabel1.setVerticalAlignment(SwingConstants.CENTER);
		lInPutLabel1.setHorizontalAlignment(SwingConstants.CENTER);
		//		lInPutLabel1.setBorder(BorderFactory.createLineBorder(Color.BLACK));

		addGridBagItem(lOutPanel, lInPutLabel1, 0, 1, 1, 1,
				GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL);

		addGridBagItem(mainPanel, lOutPanel, 0, 2, 3, 1,
				GridBagConstraints.CENTER, GridBagConstraints.BOTH);
		pack();
		setVisible(true);

	}

	private void validateEnvironment(StartGUI startGUI) {
		String version = System.getProperty("java.version");
		char minor = version.charAt(2);
		if (minor < '6') {
			JOptionPane
					.showMessageDialog(startGUI,
							"You need Java 6 to run this application \n You are presently using "
									+ version, "Update Java",
							JOptionPane.ERROR_MESSAGE);
			System.exit(0);
		}

	}

	public static void main(String[] args) {
		try {
			try {

				for (LookAndFeelInfo info : UIManager
						.getInstalledLookAndFeels()) {
					if ("Nimbus".equals(info.getName())) {
						UIManager.setLookAndFeel(info.getClassName());
						break;
					}
				}
			} catch (Exception e) {
				MetalLookAndFeel.setCurrentTheme(new DefaultMetalTheme());
				//UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
				UIManager.setLookAndFeel(new MetalLookAndFeel());
			}
		} catch (UnsupportedLookAndFeelException e1) {
			log.error("", e1);
		}

		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				createAndShowGUI();
			}
		});

	}

	private static void createAndShowGUI() {
		mStartGUI = new StartGUI();
	}

	public void actionPerformed(ActionEvent event) {
		if (event.getSource() == mOpenButton) {
			choosefile();
		} else if (event.getSource() == mResetButton) {
			System.out.println(getPreferredSize());
			mTextSeq.setText(MULTIPLE_FASTA);
			mFastaFilePath = null;
			mFileField.setText("");
		} else if (event.getSource() == mPredictButton) {
			setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
			try {
				predict();
			} catch (IOException e) {
				SystemUtil.showErrMsg(this, e.getMessage());
				log.error("", e);
			} catch (Exception e) {
				SystemUtil.showErrMsg(this, e.getMessage());
				log.error("", e);
			}
			setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
		} else if (event.getSource() == mSave) {

			JFileChooser fc = new JFileChooser();
			fc.setApproveButtonText("Save");
			fc.setApproveButtonToolTipText("Save");
			fc.setFileFilter(CsvFilter.getCsvFilter());

			int returnVal = fc.showOpenDialog(this);

			if (returnVal == JFileChooser.APPROVE_OPTION) {
				String lFastaFilePath = fc.getSelectedFile().getAbsolutePath();
				if (!lFastaFilePath.endsWith(".csv")) {
					lFastaFilePath += ".csv";
				}
				try {
					mResultTable.saveResult(lFastaFilePath);
				} catch (IOException e) {
					SystemUtil.showErrMsg(this, e.toString());
					log.error("", e);
				}
			} else {
				//  log.append("Open command cancelled by user." + newline);
			}
		} else if (event.getSource() == mHelpButton) {
			openHelp();
		}

	}

	private void openHelp() {
		if (Desktop.isDesktopSupported()) {
			Desktop desktop = Desktop.getDesktop();
			java.net.URL imgURL = getClass().getResource("/ReadMe.pdf");
            File file = new File(imgURL.getFile());
			if (file.exists()) {
				try {
					desktop.open(file);
				} catch (IOException e) {
					log.error("", e);
					SystemUtil.showErrMsg(this, e.toString());
				}
			} else {
				SystemUtil
						.showErrMsg(this,
								"ReadMe.pdf file is not found in installation directory");
			}

		} else {
			SystemUtil
					.showErrMsg(this,
							"Desktop is not supported\n Please read ReadMe.pdf from Installation folder");
		}
	}

	private void predict() throws Exception {
		String lFastaFilePath = mFastaFilePath;
		if (mFastaFilePath == null
				&& !mTextSeq.getText().equals(MULTIPLE_FASTA)) {
			lFastaFilePath = SystemUtil.saveTextFasta(mTextSeq);
		} else if (lFastaFilePath == null) {
			SystemUtil.showErrMsg(this,
					"Please enter protein sequences in a valid FASTA format");
			return;
		}
		if (lFastaFilePath != null) {

			String tmpDir = SystemUtil.getNewTmpDir();
			//			String tmpDir = "/home/rishi.das/tmp/EColi_Features/Class/Prediction_Result/decoy/shuffle";
			String[] args = { "-i=" + lFastaFilePath, "-w=" + tmpDir };
			ProgressBar.execute(args, mlog);
		}

	}

	public static void displayTableResult(ResultTable[] lTM) {
		/*for (ResultTable table : lTM) {
		 table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
		 table.setAutoCreateRowSorter(true);
		 JScrollPane jScrollPane1 = new JScrollPane();
		 jScrollPane1.setViewportView(table);
		 mStartGUI.mSeriesTabPane.addTab(table.getName(), jScrollPane1);
		 }*/

		try {
			lTM[4].setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
			lTM[4].setAutoCreateRowSorter(true);
			lTM[4].setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
			lTM[4].getColumnModel().getColumn(0).setPreferredWidth(674);
			JScrollPane jScrollPane1 = new JScrollPane();
			jScrollPane1.setViewportView(lTM[4]);
			mStartGUI.mResultTable = lTM[4];
			mStartGUI.mSave.setEnabled(true);
			mStartGUI.mSeriesTabPane.removeAll();
			mStartGUI.mSeriesTabPane.addTab("Result", jScrollPane1);

			//		        mScrollPane.setViewportView(testGuiTable.getTable());
			//		        mlog.setVisible(false);
			mStartGUI.mSeriesTabPane.setVisible(true);
			//mStartGUI.mSeriesTabPane.setPreferredSize(new Dimension(800,600));
			//mStartGUI.setSize(810, 520);
			mStartGUI.pack();
		} catch (RuntimeException e) {
			log.error("",e);
			SystemUtil.showErrMsg(mStartGUI, e.toString());
		}
	}

	private void choosefile() {
		JFileChooser fc = new JFileChooser();
		fc.setAcceptAllFileFilterUsed(false);

		int returnVal = fc.showOpenDialog(this);

		if (returnVal == JFileChooser.APPROVE_OPTION) {
			mFastaFilePath = fc.getSelectedFile().getAbsolutePath();
			mFileField.setText(mFastaFilePath);
		} else {
			//  log.append("Open command cancelled by user." + newline);
		}

	}

	public static void addGridBagItem(JPanel p, JComponent c, int x, int y,
			int width, int height, int align, int pFill) {
		GridBagConstraints gc = new GridBagConstraints();
		gc.gridx = x;
		gc.gridy = y;
		gc.gridwidth = width;
		gc.gridheight = height;
		gc.weightx = 100.0;
		gc.weighty = 100.0;
		gc.insets = new Insets(5, 5, 5, 5);
		gc.anchor = align;
		gc.fill = pFill;
		p.add(c, gc);

	}

	private void addGridBagButton(JPanel p, JComponent c, int x, int y,
			int width, int height, int align, int pFill) {
		GridBagConstraints gc = new GridBagConstraints();
		gc.gridx = x;
		gc.gridy = y;
		gc.gridwidth = width;
		gc.gridheight = height;
		gc.weightx = 100.0;
		//gc.weighty = 100.0;
		gc.insets = new Insets(5, 5, 5, 5);
		gc.anchor = align;
		gc.fill = pFill;
		p.add(c, gc);

	}

	public static JFrame getFrame() {
		return mStartGUI;
	}

}
